<template>
  <n-layout embedded>
    <n-space vertical size="small" align="center">
      <n-tooltip>
        <template #trigger>
          <n-button text @click="showPopup = true">
            <char-icon size="128" :charId="selectedChar.charId" :text="selectedChar.name" />
          </n-button>
        </template>
        选择干员
      </n-tooltip>
      <char-select-popup v-model:show="showPopup" v-model:selected="selectedChar"/>
      <n-descriptions label-placement="left" separator=" " :column="1" size="large" bordered>
        <n-descriptions-item label="精英">
          <n-space>
            <n-slider v-model:value="attr.phase" :max="maxPhase" />
            {{ attr.phase }}
          </n-space>
        </n-descriptions-item>
        <n-descriptions-item label="等级">
          <n-space>
            <n-slider v-model:value="attr.level" :max="maxLevel" :min="1" />
            {{ attr.level }}
          </n-space>
        </n-descriptions-item>
        <n-descriptions-item label="潜能">
          <n-space>
            <n-slider v-model:value="attr.potentialRank" :max="maxPotential" :min="1" />
            {{ attr.potentialRank }}
          </n-space>
        </n-descriptions-item>
        <n-descriptions-item label="信赖">
          <n-space>
            <n-slider v-model:value="attr.favor" :max="100" :step="2" />
            {{ attr.favor }}
          </n-space>
        </n-descriptions-item>
        <n-descriptions-item label="模组">
          <n-radio-group v-model:value="attr.equipId" name="rd_equip">
            <n-radio-button v-for="e in equipList" :value="e.eid" :key="e.eid" :label="e.name" />
          </n-radio-group>
        </n-descriptions-item>
        <n-descriptions-item label="技能">
          <n-radio-group v-model:value="attr.skillId" name="rd_skill">
            <n-radio-button v-for="sk in skillList" :value="sk.sid" :key="sk.sid" :label="sk.name" />
          </n-radio-group>
        </n-descriptions-item>
        <n-descriptions-item label="技能等级">
          <n-space>
            <n-slider v-model:value="attr.skillLevel" :max="maxSkillLevel" :min="1" />
            {{ attr.skillLevel }}
          </n-space>
        </n-descriptions-item>
        <n-descriptions-item label="选项">
          <n-space vertical>
            <n-space v-for="opt in optionsList">
              <n-switch v-model:value="attr.options[opt.key]" />
              {{ opt.displaytext }}
            </n-space>
          </n-space>
        </n-descriptions-item>
      </n-descriptions>
      <pre v-if="debug">{{ props }}</pre>
    </n-space>
  </n-layout>
</template>

<script lang="ts" setup>
import { computed, ref, watch } from 'vue'
import { computedAsync } from '@vueuse/core'
import { useI18n } from 'vue-i18n'
import { Maybe } from 'purify-ts/Maybe'
import { NTooltip, NButton, NCode, NSlider,
         NRadioGroup, NRadioButton, NSwitch,
         NCard, NDescriptions, NDescriptionsItem, NSpace } from 'naive-ui'
import { apiGet } from '../utils'
import { ProfessionNames, NewOp } from '../utils/types'
import { default as CharSelectPopup } from './charSelectPopup.vue'
import { default as CharIcon } from './charIcon.vue' 

// 传给该组件的参数，使用toRef取得响应式引用
// 值修改emit给上层组件
const props = defineProps({
  attr: {
    charId: String,
    name: String,
    phase: { type: Number, default: 0 },
    level: { type: Number, default: 1 },
    potentialRank: { type: Number, default: 1 },
    favor: { type: Number, default: 100 },
    skillId: String,
    skillLevel: { type: Number, default: 1 },
    equipId: String,
    options: { type: Object, default: {} }
  },
  debug: { type: Boolean, default: false }
})

const emit = defineEmits({
  'update:attr': {
    charId: String,
    name: String,
    phase: Number,
    level: Number,
    potentialRank: Number,
    favor: Number,
    skillId: String,
    skillLevel: Number,
    equipId: String,
    options: Object
  }
})

// 双向绑定
const attr = ref({...props.attr})
watch(attr, (_new, _old) => {
  emit('update:attr', _new)
})

// script setup上下文中不能使用Vue.$t，必须单独引入
const { t, locale } = useI18n() 

const showPopup = ref(false)
const selectedChar = ref({name: '选择干员'})

//const attrData = computedAsync(async () => (selectedChar.value.charId ? 
//    await apiGet(`view/character/${locale.value}/${selectedChar.value.charId}`) : null))
// chainNullable的行为和map类似，但是可以把null值封装成Nothing
const attrData = computedAsync(async () => 
                               await Maybe.fromNullable(selectedChar.value.charId)
                                          .chainNullable(charId => apiGet(`view/character/${locale.value}/${charId}`)) // Maybe<Promise<Object>>
                                          .extractNullable())
watch(attrData, (_new, _old) => {
  if (_new) {
    const phase_new = _new.charData.phases.length-1
    const defaultValue = {
      charId: selectedChar.value.charId,
      name: selectedChar.value.name,
      phase: phase_new,
      level: _new.charData.phases[phase_new].maxLevel,
      potentialRank: maxPotential.value,
      favor: 100,
      equipId: equipList.value[equipList.value.length-1].eid,
      skillId: skillList.value[skillList.value.length-1].sid,
      skillLevel: maxSkillLevel.value,
      options: {}
    }
    optionsList.value.filter(op => !op.off).map(op => {
      defaultValue.options[op.key] = true
    })
    //console.log(defaultValue)
    attr.value = defaultValue
  }
})

// 使用Maybe封装attrData
const _table = (key: string): Maybe<any> => Maybe.fromNullable(attrData.value).map(a => a[key])
const charData = () => _table('charData')
const equipData = () => _table('equipData')
const skillData = () => _table('skillData')
const optionsData = () => _table('options')

//const phaseMax = computed(() => attrData.value ? attrData.value.charData.phases.length - 1 : 0)
const maxPhase = computed(() => charData().map(x => x.phases.length-1, 0).orDefault(0))
const maxLevel = computed(() => charData().map(x => x.phases[attr.value.phase].maxLevel).orDefault(1))
const maxPotential = computed(() => charData().map(x => x.potentialRanks.length+1).orDefault(1))

const equipList = computed(() => equipData().map(x =>
                                    Object.keys(x).map(k => ({ eid: k, name: x[k].uniEquipName }))
                                  ).filter(x => x.length>0)
                                   .orDefault([{eid: null, name: '无模组'}]))
const skillList = computed(() => skillData().map(x =>
                                    Object.keys(x).map(k => ({ sid: k, name: x[k].levels[0].name }))
                                  ).filter(x => x.length>0)
                                   .orDefault([{sid: null, name: '无技能'}]))
const maxSkillLevel = computed(() => skillData().chainNullable(x => Object.values(x)[0])
                                                .map(x => x.levels.length)
                                                .orDefault(1))
const optionsList = computed(() => optionsData().orDefault([]))
</script>

<style scoped>
.n-slider {
  min-width: 200px;
}
</style>
